#include "TestRenderPass.h"
#include <SERender/Renderer/Renderer.h>
#include <SEEdit/Render/RenderFeature/DebugRenderFeature.h>
#include <SEngine/Render/RenderFeature/SkyBoxRenderFeature.h>
#include <SEngine/Render/Descriptors/ModelDescriptor.h>
#include <SEEdit/Descriptors/SelectActorDescriptor.h>
#include <SECore/Ecs/Actor.h>
#include <SECore/Ecs/Scene.h>
#include <SEngine/Ecs/Components/ModelRenderComp.h>
#include <SEngine/Ecs/Components/UuidComp.h>
#include <SERender/Descriptors/FrameDescriptor.h>
#include <SEngine/Render/Descriptors/SceneDescriptor.h>
#include <array>
#include <SEngine/Ecs/Components/LightComp.h>
#include <SEngine/Ecs/Components/TransformComp.h>
#include <SEngine/Render/RenderFeature/TextRenderFeature.h>

#include <SERender/Resourses/Loader/TextureLoader.h>

#include <SEngine/Render/Entity/Octree.h>


namespace SEngine
{



    TestRenderPass::TestRenderPass(Renderer &renderer)
        : RenderPass(renderer)
    {
        TextureLoader<Texture2D> texLoader;
        texLoader.SetInternalFormat(RGBA);
        texLoader.SetFormat(RGBA);
        texLoader.SetType(UNSIGNED_BYTE);
        texLoader.SetParameter(TEXTURE_MAG_FILTER, LINEAR);
        texLoader.SetParameter(TEXTURE_MIN_FILTER, LINEAR);
        texLoader.SetParameter(TEXTURE_WRAP_S, CLAMP_TO_EDGE);
        texLoader.SetParameter(TEXTURE_WRAP_T, CLAMP_TO_EDGE);
        m_idMap = texLoader.CreateTexture(800, 600, nullptr);
        m_idFBO = std::make_unique<FrameBuffer>();
        m_idFBO->SwapAttachments(Attachment::COLOR_ATTACHMENT0, *m_idMap);
    }      
    

    void TestRenderPass::BeginFrame()
    {
        auto & frameDescriptor = m_renderer.AnyDescriptor::GetDescriptor<FrameDescriptor>()->get();
        m_idFBO->Resize(frameDescriptor.w, frameDescriptor.h);
        m_idFBO->Use();
        m_renderer.UseFrameBuffer(*m_idFBO, [this, &frameDescriptor]() {
            m_renderer.GetDrive()->Viewport(frameDescriptor.x, frameDescriptor.y, frameDescriptor.w, frameDescriptor.h);
            m_renderer.GetDrive()->ClearColor(0.0f, 0.0f, 0.0f, 1.0f);
            m_renderer.GetDrive()->Clear(COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT);
        });
    }

    void TestRenderPass::DrawFrame()
    {
        auto & debugFeature = m_renderer.Descriptor<RenderFeature>::GetDescriptor<DebugRenderFeature>()->get();
        auto & sceneDes = m_renderer.AnyDescriptor::GetDescriptor<SceneDescriptor>()->get();
        
        m_renderer.UseFrameBuffer(*m_idFBO, [&]() {
            sceneDes.scene->Components<UuidComp, ModelRenderComp>([&](Actor & actor, UuidComp& uuidComp, ModelRenderComp& renderComp) {
                debugFeature.DrawModelWithID(renderComp.m_model, uuidComp.Hash<uint32_t>());
            });
        });

        // sceneDes.scene->Components<ModelRenderComp, TransformComp>([&](Actor & actor, ModelRenderComp & comp, TransformComp & trans) {
        //     if (comp.m_model.GetMeshFilter()) {
        //         auto & octree = comp.m_model.GetMeshFilter().Value().GetDescriptor<Octree>()->get();
        //         octree.Foreach([&](OctreeNode & node) {
        //             debugFeature.DrawBoundingBox(node.GetBoundingBox(), trans.GetModel(), glm::vec4{0.0, 1.0, 0.0, 1.0}, 2.0f);
        //         });
        //     }
        // });

    }
    
    std::vector<uint32_t> TestRenderPass::GetID(int x, int y, int w, int h)
    {
        std::vector<uint32_t> out;
        m_renderer.UseFrameBuffer(*m_idFBO, [&]() {
            std::vector<std::array<uint8_t, 4>> buf(w * h, {0, 0, 0});
            m_renderer.GetDrive()->ReadPixels(x, y, w, h, ColorFormat::RGBA, ElemType::UNSIGNED_BYTE, buf.data());
            for (auto fid : buf) {
                uint8_t pid[sizeof(uint32_t)] = {0};
                pid[0] = fid[0];
                pid[1] = fid[1];
                pid[2] = fid[2];
                pid[3] = fid[3];
                out.emplace_back(*((uint32_t*)pid));
            }
        });
        return out;
    }
} // namespace SEngine
